TypeScript class 使用私有函数实现 class
TypeScript class implements class with private functions
我正在探索 class 在 TypeScript 中实现 class 的可能性。
于是,我写了下面的代码Playground link:
class A {
private f() { console.log("f"); }
public g() { console.log("G"); }
}
class B implements A {
public g() { console.log("g"); }
}
我得到了错误:Class 'B' incorrectly implements class 'A' --- property 'f' is missing in type 'B'
加上一个建议,我的意思是 extends
。
所以我尝试创建一个名为 f
的私有字段(public
不起作用,因为它检测到它们具有不同的访问修饰符)Playground link
现在我得到错误:Class 'B' incorrectly implements class 'A'. Types have separate declarations of a private property 'f'
;这让我很困惑:
- 为什么私有成员甚至很重要 - 如果我使用不同的数据结构实现相同的算法,我是否必须为了类型检查而声明名称相同的东西?
- 为什么在将
f
作为私有函数实现时出现错误?
我不会在实践中这样做,但我很好奇为什么 TS 会这样工作。
谢谢!
在这种情况下,当前的打字稿规范是不可能的。有一个 tracked issue 用于此,但它已关闭。
Suggestion: Permit an implementing class to ignore private methods of the implementee class.
问题 Microsoft/TypeScript#18499 讨论了为什么在确定兼容性时需要私有成员。原因是:class 私有成员 可见 相同 class.
的其他实例
@RyanCavanaugh 的一个 remark 特别相关和有启发性:
Allowing the private fields to be missing would be an enormous problem, not some trivial soundness issue.
Consider this code:
class Identity {
private id: string = "secret agent";
public sameAs(other: Identity) {
return this.id.toLowerCase() === other.id.toLowerCase();
}
}
class MockIdentity implements Identity {
public sameAs(other: Identity) { return false; }
}
MockIdentity
is a public-compatible version of Identity
but attempting to use it as one will crash in sameAs
when a non-mocked copy interacts with a mocked copy.
明确一点,这是它会失败的地方:
const identity = new Identity();
const mockIdentity = new MockIdentity();
identity.sameAs(mockIdentity); // boom!
因此,您有充分的理由不能这样做。
作为一种变通方法,您可以只提取具有如下映射类型的 class 的 public 属性:
type PublicPart<T> = {[K in keyof T]: T[K]}
然后你可以 B
实施而不是 A
但 PublicPart<A>
:
class A {
private f() { console.log("f"); }
public g() { console.log("G"); }
}
// works
class B implements PublicPart<A> {
public g() { console.log("g"); }
}
希望对您有所帮助;祝你好运!
这主要是因为私有成员的可见性仅限于类型,而不是实例。这意味着类型 T 的所有对象都可以访问类型 T 的其他对象的私有。
这在主格类型语言中不是问题,因为 T 的所有实例都继承了 T 的实现,但由于打字稿是结构类型的,这意味着我们不能假设所有满足 T 的实例都具有 T 的实现class 声明类型 T。
这意味着私有范围的成员必须是类型的 public 契约的一部分,否则结构类型 T 的对象可以调用另一个对象的 non-existing 私有成员相同的结构类型。
被迫让私人成为 public 类型契约的一部分是不好的,并且可以通过将私人范围限定在实例而不是类型来避免。
当前具有 Typescript 开箱即用支持的解决方案很简单
class A {
private f() { console.log("f"); }
public g() { console.log("G"); }
}
class B implements Pick<A, keyof A> {
public g() { console.log("g"); }
}
解释:keyof A
只有returns public A
的属性(和方法),然后Pick
会向下trimA
仅显示其 public 属性及其各自的类型。
我正在探索 class 在 TypeScript 中实现 class 的可能性。
于是,我写了下面的代码Playground link:
class A {
private f() { console.log("f"); }
public g() { console.log("G"); }
}
class B implements A {
public g() { console.log("g"); }
}
我得到了错误:Class 'B' incorrectly implements class 'A' --- property 'f' is missing in type 'B'
加上一个建议,我的意思是 extends
。
所以我尝试创建一个名为 f
的私有字段(public
不起作用,因为它检测到它们具有不同的访问修饰符)Playground link
现在我得到错误:Class 'B' incorrectly implements class 'A'. Types have separate declarations of a private property 'f'
;这让我很困惑:
- 为什么私有成员甚至很重要 - 如果我使用不同的数据结构实现相同的算法,我是否必须为了类型检查而声明名称相同的东西?
- 为什么在将
f
作为私有函数实现时出现错误?
我不会在实践中这样做,但我很好奇为什么 TS 会这样工作。
谢谢!
在这种情况下,当前的打字稿规范是不可能的。有一个 tracked issue 用于此,但它已关闭。
Suggestion: Permit an implementing class to ignore private methods of the implementee class.
问题 Microsoft/TypeScript#18499 讨论了为什么在确定兼容性时需要私有成员。原因是:class 私有成员 可见 相同 class.
的其他实例@RyanCavanaugh 的一个 remark 特别相关和有启发性:
Allowing the private fields to be missing would be an enormous problem, not some trivial soundness issue. Consider this code:
class Identity { private id: string = "secret agent"; public sameAs(other: Identity) { return this.id.toLowerCase() === other.id.toLowerCase(); } } class MockIdentity implements Identity { public sameAs(other: Identity) { return false; } }
MockIdentity
is a public-compatible version ofIdentity
but attempting to use it as one will crash insameAs
when a non-mocked copy interacts with a mocked copy.
明确一点,这是它会失败的地方:
const identity = new Identity();
const mockIdentity = new MockIdentity();
identity.sameAs(mockIdentity); // boom!
因此,您有充分的理由不能这样做。
作为一种变通方法,您可以只提取具有如下映射类型的 class 的 public 属性:
type PublicPart<T> = {[K in keyof T]: T[K]}
然后你可以 B
实施而不是 A
但 PublicPart<A>
:
class A {
private f() { console.log("f"); }
public g() { console.log("G"); }
}
// works
class B implements PublicPart<A> {
public g() { console.log("g"); }
}
希望对您有所帮助;祝你好运!
这主要是因为私有成员的可见性仅限于类型,而不是实例。这意味着类型 T 的所有对象都可以访问类型 T 的其他对象的私有。
这在主格类型语言中不是问题,因为 T 的所有实例都继承了 T 的实现,但由于打字稿是结构类型的,这意味着我们不能假设所有满足 T 的实例都具有 T 的实现class 声明类型 T。
这意味着私有范围的成员必须是类型的 public 契约的一部分,否则结构类型 T 的对象可以调用另一个对象的 non-existing 私有成员相同的结构类型。
被迫让私人成为 public 类型契约的一部分是不好的,并且可以通过将私人范围限定在实例而不是类型来避免。
当前具有 Typescript 开箱即用支持的解决方案很简单
class A {
private f() { console.log("f"); }
public g() { console.log("G"); }
}
class B implements Pick<A, keyof A> {
public g() { console.log("g"); }
}
解释:keyof A
只有returns public A
的属性(和方法),然后Pick
会向下trimA
仅显示其 public 属性及其各自的类型。